# 从 flask 导入 Blueprint、request 和 jsonify
# Blueprint 用于创建 Flask 蓝图，便于组织路由
# request 用于处理 HTTP 请求
# jsonify 用于将 Python 字典或列表转换为 JSON 响应
from flask import Blueprint, request, jsonify
# 从 flask_jwt_extended 导入创建访问令牌、JWT 认证装饰器和获取 JWT 身份的函数
from flask_jwt_extended import create_access_token, jwt_required, get_jwt_identity
# 从 app 导入 Redis 客户端和日志服务
from app import redis_client, LogService
# 从 app.models.passenger_lib 导入乘客模型和可用性检查函数
from app.models.passenger_lib import Passenger, isAvailable
# 从 presenter 导入乘客展示器，用于格式化乘客数据
from presenter import PassengerPresenter
# 从 utils 导入状态码、创建响应的函数以及一些检查函数
from utils import StateCode, create_response, checkMobile, checkIdCard, checkBankCard

# 创建一个名为'register'的蓝图
register_bp = Blueprint('register', __name__)

@register_bp.route('/register', methods=['POST'])
def register():
    """
    处理用户注册请求。

    该函数接收一个包含用户注册信息的 POST 请求，
    验证各项信息的有效性，若信息有效则创建新乘客记录，
    生成访问令牌，记录日志并返回包含用户信息和令牌的成功响应。

    Returns:
        tuple: 包含 JSON 响应和 HTTP 状态码的元组。
    """
    # 获取请求中的 JSON 数据
    data = request.json
    # 从数据中提取账户名
    account = data.get('account')
    # 从数据中提取密码
    password = data.get('password')
    # 从数据中提取手机号码
    mobile_no = data.get('mobileNo')
    # 从数据中提取手机验证码
    mobile_code = data.get('mobileCode')
    # 从数据中提取身份证号码
    id_card_no = data.get('idCardNo')
    # 从数据中提取银行卡号码
    bank_card_no = data.get('bankCard')

    # 检查账户名或密码是否为空
    if not account or not password:
        # 若为空，返回参数错误的响应
        return jsonify(create_response(StateCode.PARAMS_ERROR)), 400

    # 检查手机号码格式是否正确
    if not checkMobile(mobile_no):
        # 若格式不正确，返回手机号码错误的响应
        return jsonify(create_response(StateCode.MOBILE_ERROR)), 400

    # 验证手机验证码是否正确
    if not verifyCode(mobile_no, mobile_code):
        # 若验证码不正确，返回手机验证码错误的响应
        return jsonify(create_response(StateCode.MOBILE_CODE_ERROR)), 400

    # 检查身份证号码格式是否正确
    if not checkIdCard(id_card_no):
        # 若格式不正确，返回身份证号码错误的响应
        return jsonify(create_response(StateCode.ID_CARD_ERROR)), 400

    # 检查账户名是否已存在
    if isAvailable(account):
        # 若已存在，返回用户已存在的响应
        return jsonify(create_response(StateCode.USER_ALREADY_EXISTS)), 400

    # 检查银行卡号码格式是否正确
    if not checkBankCard(bank_card_no):
        # 若格式不正确，返回银行卡号码错误的响应
        return jsonify(create_response(StateCode.BANK_CARD_ERROR)), 400

    # 创建新的乘客记录
    new_passenger = Passenger.create(data=data)
    # 为新乘客生成访问令牌
    access_token = create_access_token(identity=new_passenger.id)
    # 使用乘客展示器格式化乘客数据并添加令牌
    user_presenter = PassengerPresenter(new_passenger, {"token": access_token}).as_dict()
    # 记录日志
    LogService.log()
    # 返回包含成功状态码和用户信息的响应
    return jsonify(create_response(StateCode.SUCCESS, data=user_presenter)), 200

@register_bp.route('/auth', methods=['GET'])
@jwt_required()
def auth():
    """
    验证用户身份。

    该函数接收一个需要 JWT 认证的 GET 请求，
    获取当前用户的身份信息，从数据库中查询用户记录，
    若用户存在则格式化用户信息，记录日志并返回包含用户信息的成功响应。

    Returns:
        tuple: 包含 JSON 响应和 HTTP 状态码的元组。
    """
    # 获取当前用户的 JWT 身份信息
    current_user = get_jwt_identity()
    # 从数据库中查询当前用户的记录
    user = Passenger.query.get(current_user)
    # 检查用户是否存在
    if not user:
        # 若用户不存在，返回用户未找到的响应
        return jsonify(create_response(StateCode.USER_NOT_FOUND)), 400
    # 使用乘客展示器格式化用户数据
    user_presenter = PassengerPresenter(user, {}).as_dict()
    # 记录日志
    LogService.log()
    # 返回包含成功状态码和用户信息的响应
    return jsonify(create_response(code=StateCode.SUCCESS, data=user_presenter)), 200

def verifyCode(mobile_no, code):
    """
    验证手机验证码。

    该函数从 Redis 中获取存储的手机验证码，
    并与传入的验证码进行比较，返回验证结果。

    Args:
        mobile_no (str): 手机号码。
        code (str): 传入的验证码。

    Returns:
        bool: 验证码是否匹配。
    """
    # 从 Redis 中获取存储的验证码
    stored_code = redis_client.get(mobile_no)
    # 比较存储的验证码和传入的验证码
    return stored_code == code